/**
 * throwa un objecte fumanchou, p.ex.:
 * <tt>{cont:continuation, model:{meta:{type:""}, data:{}}}</tt>, donant el
 * <tt>model</tt>, i interrompent així l'execució del flow.
 * 
 * @param model
 * @throws un
 *             objecte fumanchou
 * @return
 */
function pause(model) {
	throw {
		cont : new Continuation(),
		model : model
	};
}

/**
 * determina si un objecte fumanchou és continuable (té definida la propietat "<tt>cont</tt>".
 * 
 * @param fumanchou
 * @return
 */
function isContinuable(fumanchou) {
	return fumanchou.cont !== undefined;
}

/**
 * donat un objecte fumanchou continuable, en restableix la continuació fent que
 * retorni el model del mateix fumanchou.
 * 
 * @param fumanchou
 * @return
 */
function callcc(fumanchou) {
	// var cont = fumanchou.cont;
	// fumanchou.cont = undefined;
	// cont(fumanchou.model);
	fumanchou.cont(fumanchou.model);
}

/**
 * @param funk
 *            la closura de flow a executar
 * @param fumanchou
 *            objecte fumanchou amb el que iniciar l'execució del flux
 * @return
 */
function ccontinue(funk, fumanchou) {

	if (isContinuable(fumanchou)) {
		// restaura la continuació
		callcc(fumanchou);
	}

	// no hi ha continuació, l'execució es comença des d'aquí
	var rfumanchou;
	try {
		rfumanchou = funk(fumanchou.model);
	} catch (e) {
		if (!isContinuable(e)) {
			// si no és continuable, "e" és un error
			throw e;
		}
		rfumanchou = e;
	}
	return rfumanchou;
}

/**
 * interromp l'execució del flux (estat salvat per continuació), amb la intenció
 * d'executar una vista.
 * 
 * @param view
 *            nom de la vista a executar
 * @param modeldata
 *            model de la vista
 * @return
 */
function sendViewAndWait(view, modeldata) {
	return pause( {
		meta : {
			type : "view",
			view : view
		},
		data : modeldata
	});
}

/**
 * interromp l'execució del flux (estat salvat per continuació), amb la intenció
 * d'executar una query SQL.
 * 
 * @param sqlQuery
 *            query SQL a executar
 * @return
 */
function sendQuery(sqlQuery) {
	return pause( {
		meta : {
			type : "sql",
			query : sqlQuery
		},
		data : {}
	});
}

/**
 * variable que retorna un flux, indicant que l'execució d'aquest ha finalitzat.
 * És el "retorn d'un flow".
 */
var flowEnd = {
	cont : undefined,
	model : {
		meta : {
			type : "end"
		},
		data : {}
	}
};
